/**
 * @file hb_app.c
 * @synopsis  
 * @author wen wjcapple@163.com
 * @version 2.0
 * @date 2016-07-05
 */

#include <dirent.h>
#include<semaphore.h>

#include "hb_app.h"
//#include "program_run_log.h"
#include "netcard.h"
#include "adpt_otdr.h"
#include "adpt_alarm.h"
#include "supplement.h"
#include "pch_op.h"
#ifdef __cplusplus
extern "C" {
#endif
//通道偏移量
volatile int32_t ch_offset = 0;
volatile int32_t card_slot = 0;
//配置文件目录
const char cfg_path[] = "/app/dev_cfg/\0";
//光纤段配置信息
const char file_fiber_sec[] = "fiber_sec_para\0";
//节点名称
const char file_node_name[] = "state_address\0";
//通道相关信息
const char file_ch_fpga[] = "ch_fpga\0";
//光纤段配置信息，里面含有指针，程序结束的时候，需要释放
struct _tagCHFiberSec *chFiberSec;
//通道硬件信息，激光器，波长，动态范围
struct _tagCHInfo chFpgaInfo;
//杂项，包含了节点名称，通道状态这样比较好管理
struct _tagDevMisc devMisc;
//硬件版本号软件版本号
struct _tagVersion DevVersion;
//网段切换控制变量
struct _tagIpSwitchCtr IPCtrl;
//pkid 控制
struct _tagCtrlPkid ctrlPkid;
struct _tagGpioFd gpio_fd;
QUICK_LOCK net_flag_lock;
struct fpga_info fpga_device_info;//fpga硬件设备信息
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initialize_sys_para 从文件中读取相关参数，并设立对应的标志
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
extern sem_t sem_UsrTest;
int32_t CH_NUM = 0;
int32_t LOCAL_CARD_TYPE = 0;
int32_t ADDR_LOCAL = 0x1000000e;
int32_t initialize_sys_para()
{
	int32_t ret, slot;
	char msg[64];
	
	memset(msg, 0, sizeof(msg));
	ret = OP_OK;
	//初始化算法模块，打开fpga设备
	initial_algor_moudle();
	//获取版本号，通道号，串并行信息
	anylyze_fpga_Info(&fpga_device_info);
	//设置全局通道数目
	CH_NUM = fpga_device_info.ch;
	
	//首先读取槽位号，初始化系统IP
	open_gpio();
	read_slot();
	light_all_led(1);
	//初始化ip控制对象
	memset(&IPCtrl, 0, sizeof(struct _tagIpSwitchCtr));
	//系统启动要检查IP
	initial_system_ip();
	//设置完Ip之后再判断通道数目
	if(CH_NUM <= 0 ||CH_NUM > CH_NUM_CEIL)
	{
		snprintf(msg, 64, "ch_num(%d), ch_num_ceil(%d)",CH_NUM, CH_NUM_CEIL);
		exit_self(1, __FUNCTION__, __LINE__,msg);
	}
	initial_device_type(CH_NUM);

	//根据通道好动态分配资源
	alloc_eq_mem(fpga_device_info.ch);
	//初始化光纤段配置，otdrdev
	initialize_fiber_sec_cfg(CH_NUM);
	initialize_otdr_dev(otdrDev,CH_NUM);
	//读取文件，初始化每个通道的波长
	initial_lamda(otdrDev,&fpga_device_info);
	initial_otdr_ctrl(&otdrTestCtrl,&fpga_device_info);
	if(otdrTestCtrl.mod == OTDR_PARALLE)
		initial_paralle_otdr();
	quick_lock_init(&net_flag_lock);
	//dev指针，设备地址，mod,bits,delay,speed
	//如果配置文件不存在则创建
	creat_folder(cfg_path);
	//如果日志文件不存在则创建
	//init_log_dir();
	reset_all_alarm_led(&gpio_fd);
	read_ch_fpga_info(&chFpgaInfo, CH_NUM);
	read_node_name_address(&devMisc);
	devMisc.ch_state.state = 0xfffffff;
	memset(&usrOtdrTest, 0, sizeof(struct _tagUsrOtdrTest));
	usrOtdrTest.state =  USR_OTDR_TEST_IDLE;
	ctrlPkid.pkid = 0x200;
	quick_lock_init(&ctrlPkid.lock);
	ret = sem_init(&sem_UsrTest,0,0);
	if(ret != 0)
		exit_self(errno, __FUNCTION__, __LINE__, "can't init sem_UsrTest\0");
	refresh_ch_state(devMisc.ch_state.state);
	init_dypulse();
	create_usr_tsk();
	return ret;
}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initial_device_type 根据通道数目设定设备的源地址和类型
 *
 * @param num_ch	通道数目
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t initial_device_type(int32_t num_ch)
{
	char msg[64];
	switch(num_ch)
	{
		case 1:
			LOCAL_CARD_TYPE = 0;
			ADDR_LOCAL = 0x1000000e;
			break;
		case 2:
			LOCAL_CARD_TYPE = 1;
			ADDR_LOCAL = 0x2000000e;
			break;
		case 4:
			LOCAL_CARD_TYPE = 2;
			ADDR_LOCAL = 0x3000000e;
			break;
		case 8:
			LOCAL_CARD_TYPE = 5;
			ADDR_LOCAL = 0x6000000e;
			break;
		default:
			snprintf(msg, 64, "protol undefine ch_num(%d),no type, no addr ",CH_NUM);
			exit_self(1, __FUNCTION__, __LINE__,msg);
			break;
	}
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  alloc_eq_mem 分配设备资源，otdrDev，chFiberSec, chFpgaInfo
 *
 * @param ch_num 通道数码
 *
 * @returns   0 如果出错，直接退出
 */
/* ----------------------------------------------------------------------------*/
int32_t alloc_eq_mem(int32_t ch_num)
{
	char msg[64];
	int32_t msg_len;
	msg_len = 63;
	memset(msg, 0, sizeof(msg));
	otdrDev = NULL;
	chFiberSec = NULL;
	chFpgaInfo.para = NULL;

	otdrDev = malloc(ch_num*sizeof(struct _tagOtdrDev));
	if(otdrDev == NULL)
	{
		snprintf(msg,msg_len,"malloc otdrDev error ch_num %d",ch_num); 
		exit_self(errno,__FUNCTION__,__LINE__,msg);
	}
	memset(otdrDev, 0, sizeof(struct _tagOtdrDev)*ch_num);
	chFiberSec = malloc(ch_num*sizeof(struct _tagCHFiberSec));
	if(chFiberSec == NULL)
	{
		snprintf(msg,msg_len,"malloc chFiberSec error ch_num %d",ch_num); 
		exit_self(errno,__FUNCTION__,__LINE__,msg);
	}
	memset(chFiberSec, 0, sizeof(struct _tagCHFiberSec)*ch_num);
	chFpgaInfo.para = malloc(ch_num*sizeof(struct _tagFpgaPara));
	if(chFpgaInfo.para == NULL)
	{
		snprintf(msg,msg_len,"malloc chFiberSec error ch_num %d",ch_num); 
		exit_self(errno,__FUNCTION__,__LINE__,msg);
	}
	
	memset(chFpgaInfo.para, 0, sizeof(struct _tagFpgaPara)*ch_num);
	return 0;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  free_eq_mem 释放内部资源
 *
 * @param ch_num
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t free_eq_mem(int32_t ch_num)
{
	int i;

	if(otdrDev != NULL)
		free(otdrDev);
	//chFiberSec 释放之前需要释放内部资源
	if(chFiberSec != NULL)
	{
		for(i = 0; i < ch_num;i++)
			free_fiber_sec_buf(&chFiberSec[i]);
		free(chFiberSec);
	}
	if(chFpgaInfo.para != NULL)
		free(otdrDev);
	
	otdrDev = NULL;
	chFiberSec = NULL;
	chFpgaInfo.para = NULL;

}

//初始化otdr控制变量
int32_t initial_otdr_ctrl(struct _tagOtdrTestCtrl *pTestCtrl, struct fpga_info *fpga)
{
	int32_t i,ch_num_t;
	int32_t is_init = 0;
	memset(pTestCtrl, 0, sizeof(struct _tagOtdrTestCtrl));
	pTestCtrl->ch_num = fpga->ch;

	i = 1 << 4;

	if(((fpga->hw_ver & i) == 0) && ((fpga->hw_ver & 1) == 1))
		pTestCtrl->mod = OTDR_PARALLE;
	else
		pTestCtrl->mod = OTDR_SERRI;

	ch_num_t = pTestCtrl->ch_num;
	for(i = 0; i < CH_NUM; i++)
	{
		if(otdrDev[i].ch_ctrl.is_cfged){
			pTestCtrl->monitor_num++;
			is_init = 1;
		}
		else {
			//并行otdr的时候需要设立标志位，判断是否轮询一遍
			pTestCtrl->alarm_syn = pTestCtrl->alarm_syn | (1 << i);
		}
	}
	if(is_init == 0)
		pTestCtrl->is_send_alarm = 1;
	return 0;
}
//更新被监测的通道数目
int32_t refresh_monior_ch_num()
{
	int32_t i,monitor_num;
	monitor_num = 0;

	for(i = 0; i < CH_NUM; i++)
	{
		if(otdrDev[i].ch_ctrl.is_cfged)
			monitor_num++;
	}
	return monitor_num;
}
//初始化算法模块
int32_t initial_algor_moudle()
{
	int32_t ret;
	ret = 0;
	fpga_device = NULL;
#ifndef TARGET_X86
	ret = fpga_open("/dev/spidev3.0", &fpga_device, 5000000);
	if(ret != 0){
		PR_X("open spidev3.0 error ret %d \n",ret);
		exit_self(errno, __FUNCTION__, __LINE__, "can't open spidev3.0\0");
	}
#endif

	spi_ctrl.fpga = fpga_device;
	otdr_open(&spi_ctrl);
	pthread_mutex_init(&spi_ctrl.mutex_fpga, NULL);
	//configOtdrAlgo("/opt/TR600plus/config/otdralgo_config",16000);
	return ret;
}
extern int fpga_info(struct fpga_dev *dev,  struct fpga_info *out);
int32_t anylyze_fpga_Info(struct fpga_info *fpga)
{
	int32_t ret;
	if(fpga_device == NULL)
		exit_self(1,__FUNCTION__,__LINE__,"fpga_device == NULL");

	ret = fpga_info(fpga_device,fpga);
	
	return ret;
}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initial_lamda 从文件中读取波长值
 *
 * @param potdr 
 * @param pfpga
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t initial_lamda(struct _tagOtdrDev *potdr, struct fpga_info *pfpga)
{
	int32_t i, ret, ch_num_t;
	char file_path[64], msg[64];
		char otdr_name[48];
	int32_t otdr_code, OtdrLasersMM[16], OtdrLasersSM[16],VFLLasers[2];
	int32_t *type;
	struct _tagCHCtrl *pch_ctrl;

	FILE *fp;

	memset(OtdrLasersMM, 0, sizeof(OtdrLasersMM));
	memset(OtdrLasersSM, 0, sizeof(OtdrLasersMM));
	memset(VFLLasers, 0, sizeof(VFLLasers));
	
	ret = getHWInfo(&spi_ctrl, 
			otdr_name, 
			&otdr_code, 
			OtdrLasersMM, 
			OtdrLasersSM,
			VFLLasers,
			&type);
	assert(ret == 0);
	

	ret = 1;
	memset(file_path, 0, sizeof(file_path));
	memset(msg, 0, sizeof(msg));
	snprintf(file_path,64 , "%s%s.cfg",cfg_path, "lamda");

	fp = fopen(file_path,"r");
	if(fp == NULL)
	{
		snprintf(msg, 64,"open file error %s", file_path);
		goto usr_exit;
	}
	fscanf(fp, "%d", &ch_num_t);
	if (ch_num_t != pfpga->ch)
	{
		snprintf(msg, 64,"ch_num != fpga.ch error %d %d",ch_num_t,pfpga->ch);
		fclose(fp);
		goto usr_exit;
	}
	for(i = 0; i < ch_num_t;i++)
	{

		pch_ctrl = &potdr[i].ch_ctrl;
		ret = fscanf(fp, "%d", &pch_ctrl->lamda);
		pch_ctrl->lamda_type = type;

		if(ret == -1)
		{
			snprintf(msg, 64,"read lamda error");
			goto usr_exit;
		}
	}
	fclose(fp);

	ret = 0;



usr_exit:
	if(ret != 0)
		exit_self(ret, __FUNCTION__, __LINE__, msg);
	return ret;	
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initialize_fiber_sec_cfg 读取配置文件，初始化光纤段参数
 *		初始化光纤段参数之后方可初始化otdrDev
 * @param pFiberSec
 * @param num
 *
 * @returns   0成功，其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t initialize_fiber_sec_cfg()
{
	int32_t ret, i;
	ret = OP_OK;
	
	for(i = 0; i < CH_NUM;i++)
	{
		//alarm_disappear(&spiDev,i);
		quick_lock_init(&chFiberSec[i].lock);
		memset(&chFiberSec[i].para,0, sizeof(struct _tagFiberSecCfg));		
		memset(&chFiberSec[i].alarm,0, sizeof(struct _tagSecFiberAlarm));		
		memset(&chFiberSec[i].statis,0, sizeof(struct _tagFiberStatisData));
		memset(&chFiberSec[i].alarm, 0, sizeof(struct _tagSecFiberAlarm));		
		ret = read_fiber_sec_para(i,&chFiberSec[i]);
	}
	adjust_fiber_sec_cfg_ch();

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initialize_otdr_dev 用光纤段参数初始化otdrDev
 *
 * @param pOtdrDev
 * @param pFiberSec
 * @param ch_num
 *
 * @returns   0 成功，其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t initialize_otdr_dev(struct _tagOtdrDev *pOtdrDev,
		int32_t ch_num)
{
	int ret, i;
	struct _tagFiberSecCfg *pFiberSec;
	int32_t offset;
	struct _tagCycCurv *pcurv;
	struct _tagHostOtdrPara HostPara;
	struct _tagSecLoss *psec_loss;
	OtdrTestResult_t ch_tr;
	ch_tr.Ai = malloc(sizeof(float)*DATA_LEN);
	if(ch_tr.Ai == NULL)
		 exit_self(errno,__FUNCTION__,__LINE__,"malloc ch_ti error");

	ret = OP_OK;
	offset = sizeof(struct _tagCHCtrl) + sizeof( struct _tagCHPara)*2;
		
	for(i = 0; i < ch_num;i++)
	{
		memset(&pOtdrDev[i], 0, offset);
		pcurv = &pOtdrDev[i].curv;
		quick_lock_init(&pcurv->lock);
		sem_init(&pOtdrDev[i].sem_msg, 0, 0);
		memset(&pcurv->curv, 0, sizeof(struct _tagUpOtdrCurv));
		if(chFiberSec[i].para.is_initialize)
		{
			memcpy(&HostPara.MeasureLength_m, &chFiberSec[i].para.otdr_param.range,\
					sizeof(struct _tagHostOtdrPara) - 8);
			HostPara.slot = chFiberSec[i].para.otdr_param.slot;
			HostPara.pipe = chFiberSec[i].para.otdr_param.pipe;

			convert_para_host2algor(&HostPara,&otdrDev[i].ch_para);
			pOtdrDev[i].ch_ctrl.is_cfged = 1;
			pOtdrDev[i].ch_ctrl.st_fiber_len = chFiberSec[i].para.test_result.range;
			pOtdrDev[i].ch_ctrl.st_pulse = HostPara.PulseWidth_ns;
			psec_loss = &pOtdrDev[i].ch_ctrl.sec_loss;
			convert_tr_fbsec2algor(&chFiberSec[i],&ch_tr);
			init_sec_loss_len(psec_loss, &ch_tr, &chFiberSec[i]);

		}


	}
	free(ch_tr.Ai);
	ch_tr.Ai = NULL;
	return ret;
}


/* --------------------------------------------------------------------------*/
/**
 * @synopsis  creat_folder 创建文件夹 如果两个线程同时条用这个函数创建同名同
 *		路径下的文件夹就悲催了，在某些情况下回返回错误，难道要加锁?
 * @param folder_path[]	文件夹路径+文件名
 *
 * @returns   0 成功 其他系统给出的错误码
 */
/* ----------------------------------------------------------------------------*/
int32_t creat_folder(const char folder_path[])
{
	int ret;
	DIR *dir_folder;
	ret = 0;
	dir_folder = opendir(folder_path);
	//如果目录为空，就创建
	if(dir_folder == NULL)
	{
		mkdir(folder_path,0775);
	}
	dir_folder = opendir(folder_path);
	//如果打开创建后的目录，仍然失败那么返回
	if(dir_folder == NULL)
	{
		ret = errno;
		goto usr_exit;
	}

usr_exit:
	if(dir_folder != NULL)
		closedir(dir_folder);
	return ret;
}
int32_t clr_fiber_sec_para(int32_t ch,
		struct _tagCHFiberSec *pch_fiber_sec,
		struct _tagOtdrDev *potdr_dev)
{
	char file_path[FILE_PATH_LEN] = {0};

	snprintf(file_path,FILE_PATH_LEN , "%s%s_%d.cfg",cfg_path, file_fiber_sec,ch);
	//如果段数目为0，那么就是清空该光线段为的配置信息
	quick_lock(&pch_fiber_sec->lock);
	if(pch_fiber_sec->para.is_initialize)
	{
		remove(file_path);
		free_fiber_sec_buf(pch_fiber_sec);
		free_alarmmodule_resource(&pch_fiber_sec->adpt_moudle);
	}
	potdr_dev->ch_ctrl.refresh_para = 1;
	sem_post(&potdr_dev->sem_msg);
	quick_unlock(&pch_fiber_sec->lock);
	set_ch_alarm_status(ch, 0,&chAlarmDis);
	return 0;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  save_fiber_sec_para 用户配置光纤段参数，需要保存文件，同时通知
 *		对应的通道更新参数使用文件锁加锁,并在此更新对应通道的光线段
 *		参数,光纤段参数的释放在此处理，赋值在读取配置通道时，更新在此
 * @param ch		通道 从0开始，从0开始，从0开始，重要的事情说三遍
 * @param pfiber_sec	光线段参数
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t save_fiber_sec_para(int ch,
		struct tms_fibersectioncfg *pfiber_sec,
		struct _tagCHFiberSec *pch_fiber_sec,
		struct _tagOtdrDev *potdr_dev
		)
{
	int ret, counts, tmp;
	char file_path[FILE_PATH_LEN] = {0};
	FILE *fp;
	struct _tagFiberSecHead secHead;
	struct _tagFiberSecCfg *psec_cfg;
	struct _tagSecFiberAlarm *pAlarm;
	struct _tagFiberStatisData *pStatis;

	pAlarm = &pch_fiber_sec->alarm;
	pStatis = &pch_fiber_sec->statis;

	pAlarm = &pch_fiber_sec->alarm;

	secHead.sec_num = pfiber_sec->fiber_hdr->count;
	secHead.data_num = pfiber_sec->otdr_hdr->count;
	secHead.event_num = pfiber_sec->event_hdr->count;
	ret = OP_OK;
	fp = NULL;
	snprintf(file_path,FILE_PATH_LEN , "%s%s_%d.cfg",cfg_path, file_fiber_sec,ch);
	//如果段数目为0，那么就是清空该光线段为的配置信息
	if(!secHead.sec_num )
	{
		quick_lock(&pch_fiber_sec->lock);
		if(pch_fiber_sec->para.is_initialize)
		{
			ret = remove(file_path);
			free_fiber_sec_buf(pch_fiber_sec);
			free_alarmmodule_resource(&pch_fiber_sec->adpt_moudle);
			system("sync");
		}
		potdr_dev->ch_ctrl.refresh_para = 1;
		sem_post(&potdr_dev->sem_msg);
		quick_unlock(&pch_fiber_sec->lock);
		//alarm_disappear(&spiDev,ch);
		return ret;
	}

	fp = NULL;
	ret = OP_OK;
	//获取日志名字
	fp = fopen(file_path,"wb");
	if(fp == NULL){
		ret = errno;
		goto usr_exit;

	}
	//保存光纤段可变信息
	counts = fwrite(&secHead, sizeof(struct _tagFiberSecHead),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	//光纤段头信息
	counts = fwrite(pfiber_sec->fiber_hdr, sizeof( struct tms_fibersection_hdr),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	//光纤段具体内容
	tmp = pfiber_sec->fiber_hdr->count;
	counts = fwrite(pfiber_sec->fiber_val, \
			sizeof( struct tms_fibersection_val),tmp,fp);
	if(counts != tmp){
		ret = errno;
		goto usr_exit;
	}
	//测量参数
	counts = fwrite(pfiber_sec->otdr_param, \
			sizeof( struct tms_otdr_param),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	//测量结果
	counts = fwrite(pfiber_sec->test_result, \
			sizeof( struct tms_test_result),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	//数据点
	counts = fwrite(pfiber_sec->otdr_hdr, \
			sizeof( struct tms_hebei2_data_hdr),1,fp);

	tmp = pfiber_sec->otdr_hdr->count;
	counts = fwrite(pfiber_sec->otdr_val,sizeof( struct tms_hebei2_data_val),\
			tmp, fp);
	if(counts != tmp){
		ret = errno;
		goto usr_exit;
	}
	//事件点信息
	counts = fwrite(pfiber_sec->event_hdr, \
			sizeof( struct tms_hebei2_event_hdr),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	tmp = pfiber_sec->event_hdr->count;
	counts = fwrite(pfiber_sec->event_val,sizeof(struct tms_hebei2_event_val),\
			tmp,fp);
	if(counts != tmp){
		ret = errno;
		goto usr_exit;
	}
	ret = OP_OK;
	fclose(fp);
	fp = NULL;
	//更新光线段参数
	quick_lock(&pch_fiber_sec->lock);
	ret = alloc_fiber_sec_buf(secHead, pch_fiber_sec);
	
	psec_cfg = &pch_fiber_sec->para;
	if(!ret)
	{
		memcpy(&psec_cfg->event_hdr, pfiber_sec->event_hdr, sizeof(struct tms_hebei2_event_hdr));
		memcpy(psec_cfg->event_val, pfiber_sec->event_val, sizeof(struct tms_hebei2_event_val)*secHead.event_num);
		memcpy(&psec_cfg->fiber_hdr, pfiber_sec->fiber_hdr, sizeof(struct tms_fibersection_hdr));
		memcpy(psec_cfg->fiber_val, pfiber_sec->fiber_val, sizeof(struct tms_fibersection_val)*secHead.sec_num);

		memcpy(&psec_cfg->otdr_hdr, pfiber_sec->otdr_hdr, sizeof(struct tms_hebei2_data_hdr));
		memcpy(psec_cfg->otdr_val, pfiber_sec->otdr_val, sizeof(struct tms_hebei2_data_val)*secHead.data_num);

		memcpy(&psec_cfg->otdr_param, pfiber_sec->otdr_param, sizeof(struct tms_otdr_param));
		memcpy(&psec_cfg->test_result, pfiber_sec->test_result, sizeof(struct tms_test_result));

		pAlarm->ch = ch + ch_offset;
		pAlarm->sec_num = secHead.sec_num;
		pAlarm->chang = 0;
		pStatis->sec_num = secHead.sec_num;
		pStatis->counts = 0;
		pStatis->state = 0;

		psec_cfg->is_initialize = 1;
		psec_cfg->error_num = 0;
		potdr_dev->ch_ctrl.refresh_para = 1;
		sem_post(&potdr_dev->sem_msg);
	}
		
	quick_unlock(&pch_fiber_sec->lock);
	set_ch_alarm_status(ch, 0,&chAlarmDis);

usr_exit:
	if(fp != NULL)
		fclose(fp);
	printf("%s():%d: save fiber sec para ch %d ret %d .\n",\
			__FUNCTION__, __LINE__, ch, ret);

	system("sync");
	return ret;

}
int32_t initial_ch_fiber_sec(int ch,
		struct tms_fibersectioncfg *pfiber_sec,
		struct _tagCHFiberSec *pch_fiber_sec,
		struct _tagOtdrDev *potdr_dev	)
{
	int ret, counts, tmp;
	struct _tagFiberSecHead secHead;
	struct _tagFiberSecCfg *psec_cfg;
	struct _tagSecFiberAlarm *pAlarm;
	struct _tagFiberStatisData *pStatis;

	pAlarm = &pch_fiber_sec->alarm;
	pStatis = &pch_fiber_sec->statis;

	pAlarm = &pch_fiber_sec->alarm;

	secHead.sec_num = pfiber_sec->fiber_hdr->count;
	secHead.data_num = pfiber_sec->otdr_hdr->count;
	secHead.event_num = MAX_EVENT_NUM;
	ret = OP_OK;
	//更新光线段参数
	quick_lock(&pch_fiber_sec->lock);
	ret = alloc_fiber_sec_buf(secHead, pch_fiber_sec);
	
	psec_cfg = &pch_fiber_sec->para;
	if(!ret)
	{
		memcpy(&psec_cfg->event_hdr, pfiber_sec->event_hdr, sizeof(struct tms_hebei2_event_hdr));
		memcpy(psec_cfg->event_val, pfiber_sec->event_val, sizeof(struct tms_hebei2_event_val)*secHead.event_num);
		memcpy(&psec_cfg->fiber_hdr, pfiber_sec->fiber_hdr, sizeof(struct tms_fibersection_hdr));
		memcpy(psec_cfg->fiber_val, pfiber_sec->fiber_val, sizeof(struct tms_fibersection_val)*secHead.sec_num);

		memcpy(&psec_cfg->otdr_hdr, pfiber_sec->otdr_hdr, sizeof(struct tms_hebei2_data_hdr));
		memcpy(psec_cfg->otdr_val, pfiber_sec->otdr_val, sizeof(struct tms_hebei2_data_val)*secHead.data_num);

		memcpy(&psec_cfg->otdr_param, pfiber_sec->otdr_param, sizeof(struct tms_otdr_param));
		memcpy(&psec_cfg->test_result, pfiber_sec->test_result, sizeof(struct tms_test_result));

		pAlarm->ch = ch + ch_offset;
		pAlarm->sec_num = secHead.sec_num;
		pAlarm->chang = 0;
		pStatis->sec_num = secHead.sec_num;
		pStatis->counts = 0;
		pStatis->state = 0;

		psec_cfg->is_initialize = 1;
		psec_cfg->error_num = 0;
		potdr_dev->ch_ctrl.refresh_para = 1;
		sem_post(&potdr_dev->sem_msg);
	}
		
	quick_unlock(&pch_fiber_sec->lock);
	set_ch_alarm_status(ch, 0,&chAlarmDis);

usr_exit:
	printf("%s():%d:  ch %d ret %d .\n",\
			__FUNCTION__, __LINE__, ch, ret);
	return ret;

}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  read_fiber_sec_para 从文件中读取光纤段参数，注意与保存光纤段数据
 *		类型一样, 检查读取的光纤段数目，数据点数目，事件点数目是否
 *		与头信息一致，如果不一致，则文件损坏
 * @param ch 通道
 * @param pfiber_sec 指向光纤段配置缓冲区
 *
 * @returns   0 成功，其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t read_fiber_sec_para(int ch, struct _tagCHFiberSec *pch_fiber_sec)
{

	int32_t ret, counts, tmp;
	uint8_t is_free, is_lock;
	char file_path[FILE_PATH_LEN] = {0};
	FILE *fp;
	struct _tagFiberSecHead secHead;
	struct _tagFiberSecCfg	*pfiber_sec;
	struct _tagSecFiberAlarm *pAlarm;
	//统计数据，光线段数目有关系
	struct _tagFiberStatisData *pStatis;
	pAlarm = &pch_fiber_sec->alarm;
	pStatis = &pch_fiber_sec->statis;

	is_free = 0;
	is_lock	= 0;
	pfiber_sec = &(pch_fiber_sec->para);
	snprintf(file_path,FILE_PATH_LEN , "%s%s_%d.cfg",cfg_path, file_fiber_sec,ch);
	fp = NULL;
	ret = OP_OK;
	//打开文件
	fp = fopen(file_path,"rb");
	if(fp == NULL){
		ret = errno;
		goto usr_exit;

	}
	counts = fread(&secHead, sizeof(struct _tagFiberSecHead),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	quick_lock(&pch_fiber_sec->lock);
	is_lock = 1;
	//为光纤段，数据段，时间点等位置分配空间
	ret = alloc_fiber_sec_buf(secHead, pch_fiber_sec);
	if(ret != OP_OK)
		goto usr_exit;
	is_free = 1;
	//光纤段头信息
	counts = fread(&pfiber_sec->fiber_hdr, sizeof( struct tms_fibersection_hdr),1,fp);
	if(counts != 1|| pfiber_sec->fiber_hdr.count != secHead.sec_num){
		if(counts != 1)
			ret = errno;
		else
			ret = FILE_RUIN;
		goto usr_exit;
	}
	//光纤段具体内容
	tmp = pfiber_sec->fiber_hdr.count;
	counts = fread(pfiber_sec->fiber_val, \
			sizeof( struct tms_fibersection_val),tmp,fp);
	if(counts != tmp){
		ret = errno;
		goto usr_exit;
	}
	//测量参数
	counts = fread(&pfiber_sec->otdr_param, \
			sizeof( struct tms_otdr_param),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	//测量结果
	counts = fread(&pfiber_sec->test_result, \
			sizeof( struct tms_test_result),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	//数据点
	counts = fread(&pfiber_sec->otdr_hdr, \
			sizeof( struct tms_hebei2_data_hdr),1,fp);
	if(counts != 1|| pfiber_sec->otdr_hdr.count != secHead.data_num){
		if(counts != 1)
			ret = errno;
		else
			ret = FILE_RUIN;
		goto usr_exit;
	}

	tmp = pfiber_sec->otdr_hdr.count;
	counts = fread(pfiber_sec->otdr_val,sizeof( struct tms_hebei2_data_val),\
			tmp, fp);
	if(counts != tmp){
		ret = errno;
		goto usr_exit;
	}
	//事件点信息
	counts = fread(&pfiber_sec->event_hdr, \
			sizeof( struct tms_hebei2_event_hdr),1,fp);

	if(counts != 1|| pfiber_sec->event_hdr.count != secHead.event_num){
		if(counts != 1)
			ret = errno;
		else
			ret = FILE_RUIN;
		goto usr_exit;
	}

	tmp = pfiber_sec->event_hdr.count;
	counts = fread(pfiber_sec->event_val,sizeof(struct tms_hebei2_event_val),\
			tmp,fp);
	if(counts != tmp){
		ret = errno;
		goto usr_exit;
	}
	ret = OP_OK;
	fclose(fp);
	fp = NULL;
	pAlarm->ch = ch + ch_offset;
	pAlarm->sec_num = secHead.sec_num;
	pAlarm->chang = 0;
	pStatis->sec_num = secHead.sec_num;
	pStatis->counts = 0;
	pStatis->state = 0;
	pfiber_sec->is_initialize = 1;
	pfiber_sec->error_num = 0;

usr_exit:
	if(is_lock)
		quick_unlock(&pch_fiber_sec->lock);
	if(fp != NULL)
		fclose(fp);
	if(ret != OP_OK)
		free_fiber_sec_buf(pch_fiber_sec);
	printf("%s():%d: read fiber sec para ch %d ret %d .\n",\
			__FUNCTION__, __LINE__, ch, ret);
	return ret;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  alloca_fiber_sec_buf 分配光纤段缓冲区,如果缓冲区已经存在，并且请求的
 *		小于已经存在的缓冲区，则不分配直接使用原来的,分配之后清空告警
 * @param secHead	 数据点数目，光纤段数目，事件点数目
 * @param pCHFiberSec	
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t alloc_fiber_sec_buf(struct _tagFiberSecHead secHead, struct _tagCHFiberSec *pCHFiberSec)
{
	int32_t ret, count, i;
	char log[NUM_CHAR_LOG_MSG] = {0};
	ret = OP_OK;
	//光线段，曲线，告警门限
	struct _tagFiberSecCfg *pFiberSecCfg;
	//告警，和光线段数目有关系
	struct _tagSecFiberAlarm *pAlarm;
	//统计数据，光线段数目有关系
	struct _tagFiberStatisData *pStatis;

	pFiberSecCfg = &pCHFiberSec->para;
	pAlarm = &pCHFiberSec->alarm;
	pStatis = &pCHFiberSec->statis;
	
	count = secHead.sec_num;
	//分配存储空间，如果存储空间已经存在并且需要的存储空间小于已分配的，则不再分配
	if(pFiberSecCfg->fiber_val == NULL)
		pFiberSecCfg->fiber_val = (struct tms_fibersection_val*)\
			malloc(sizeof(struct tms_fibersection_val)*count);
	else if(count > pFiberSecCfg->fiber_hdr.count){
		free(pFiberSecCfg->fiber_val);
		pFiberSecCfg->fiber_val =  (struct tms_fibersection_val*)\
			malloc(sizeof(struct tms_fibersection_val)*count);
	}
	//分配告警存储空间
	if(pAlarm->buf == NULL)
		pAlarm->buf = malloc(sizeof(struct _tagAlarm)*count);
	else if(count > pFiberSecCfg->fiber_hdr.count){
		free(pAlarm->buf);
		pAlarm->buf = malloc(sizeof(struct _tagAlarm)*count);
	}
	//分配告警存储空间
	if(pAlarm->pcurv == NULL)
		pAlarm->pcurv = malloc(sizeof(struct _tagUpOtdrCurv));

	//分配统计数据存储空间
	if(pStatis->buf == NULL)
		pStatis->buf = malloc(sizeof( struct _tagSecStatisData)*count);
	else if(count > pFiberSecCfg->fiber_hdr.count){
		free(pStatis->buf);
		pStatis->buf = malloc(sizeof(struct _tagSecStatisData)*count);
	}
	//分配采样点数存储空间
	count = secHead.data_num;
	if(pFiberSecCfg->otdr_val == NULL)
		pFiberSecCfg->otdr_val = (struct tms_hebei2_data_val *)\
			malloc(count * sizeof(struct tms_hebei2_data_val));
	else if(count > pFiberSecCfg->otdr_hdr.count){
		free(pFiberSecCfg->otdr_val);
		pFiberSecCfg->otdr_val = (struct tms_hebei2_data_val *)\
			malloc(count * sizeof(struct tms_hebei2_data_val));

	}
	//分配事件点存储空间
	count = secHead.event_num;
	if(pFiberSecCfg->event_val == NULL)
		pFiberSecCfg->event_val = (struct tms_hebei2_event_val *)\
			malloc(count * sizeof(struct tms_hebei2_event_val));
	else if(count > pFiberSecCfg->event_hdr.count){
		free(pFiberSecCfg->event_val);
		pFiberSecCfg->event_val = (struct tms_hebei2_event_val *)\
			malloc(count * sizeof(struct tms_hebei2_event_val));
	}
	//检查分配结果是否正确
	if(!pFiberSecCfg->fiber_val||!pFiberSecCfg->otdr_val || !pFiberSecCfg->event_val\
			|| !pAlarm->buf || !pStatis->buf|| !pAlarm->pcurv)
	{
		free_fiber_sec_buf(pCHFiberSec);
		ret = NEW_BUF_FAIL;
		exit_self(errno,__FUNCTION__, __LINE__,"new buf fail\0");
	}
	else{
		pFiberSecCfg->is_initialize = 0;
		pFiberSecCfg->error_num = 0;
		count = secHead.sec_num;
		memset(pAlarm->buf, 0,sizeof(struct _tagAlarm)*count);
		memset(pStatis->buf, 0,sizeof(struct _tagSecStatisData)*count);
		//2017-09-14初始化成-1 与告警级别为0 区分,后面的判断也是以大于0为有告警
		for(i = 0; i < count; i++)
			pAlarm->buf[i].lev = -36;
		pAlarm->alarm_num = 0;
		pAlarm->chang = 0;
		pAlarm->sec_num = count;

	}

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  free_fiber_sec_buf 释放包括光线段参数，告警缓冲区，统计缓冲区
 *
 * @param pCHFiberSec
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t free_fiber_sec_buf(struct _tagCHFiberSec *pCHFiberSec)
{
	//光线段，曲线，告警门限
	struct _tagFiberSecCfg *pFiberSecCfg;
	//告警，和光线段数目有关系
	struct _tagSecFiberAlarm *pAlarm;
	//统计数据，光线段数目有关系
	struct _tagFiberStatisData *pStatis;

	pFiberSecCfg = &pCHFiberSec->para;
	pAlarm = &pCHFiberSec->alarm;
	pStatis = &pCHFiberSec->statis;

	int32_t ret;
	ret = OP_OK;
	//删除光纤段
	if(pFiberSecCfg->fiber_val != NULL){
		free(pFiberSecCfg->fiber_val);
		pFiberSecCfg->fiber_val = NULL;
	}
	//删除otdr缓冲区
	if(pFiberSecCfg->otdr_val != NULL){
		free(pFiberSecCfg->otdr_val);
		pFiberSecCfg->otdr_val = NULL;
	}
	//事件点缓冲区
	if(pFiberSecCfg->event_val != NULL){
		free(pFiberSecCfg->event_val);
		pFiberSecCfg->event_val = NULL;
	}
	//告警缓冲区
	if(pAlarm->buf != NULL){
		free(pAlarm->buf);
		pAlarm->buf = NULL;
	}
	if(pAlarm->pcurv != NULL){
		free(pAlarm->pcurv);
		pAlarm->pcurv = NULL;
	}
	//释放统计数据缓冲区
	if(pStatis->buf != NULL){
		free(pStatis->buf);
		pStatis->buf = NULL;
	}

	//初始化标志设为0
	pFiberSecCfg->is_initialize = 0;
	pFiberSecCfg->error_num = 0;
	return ret;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  quick_lock_init 根据宏定义初始化锁函数
 *
 * @param plock
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t quick_lock_init(QUICK_LOCK *plock)
{
#ifdef LOCK_TYPE_SPIN
	pthread_spin_init(plock, 0);
#else
	pthread_mutex_init(plock,NULL);
#endif
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  quick_lock 自定义快速锁的上锁函数
 *
 * @param plock
 *
 * @returns   0
 */
/* ----------------------------------------------------------------------------*/
int32_t quick_lock( QUICK_LOCK *plock)
{
	int32_t ret;
	ret = OP_OK;
#ifdef LOCK_TYPE_SPIN
	pthread_spin_lock(plock);
#else
	pthread_mutex_lock(plock);
#endif
	return ret;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  quick_unlock 字定义快速锁解锁
 *
 * @param plock
 *
 * @returns   0
 */
/* ----------------------------------------------------------------------------*/
int32_t quick_unlock( QUICK_LOCK *plock)
{
	int32_t ret;
	ret = OP_OK;
#ifdef LOCK_TYPE_SPIN
	pthread_spin_unlock(plock);
#else
	pthread_mutex_unlock(plock);
#endif
	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  save_ch_fpga_info 保存fpga信息
 *
 * @param pch_fpga_info
 * @param ch_num
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t save_ch_fpga_info(const struct _tagCHInfo *pch_fpga_info,int32_t ch_num)
{
	int32_t ret, counts, tmp;
	char file_path[FILE_PATH_LEN] = {0};
	FILE *fp;

	snprintf(file_path,FILE_PATH_LEN , "%s%s.cfg",cfg_path, file_ch_fpga);
	fp = NULL;
	ret = OP_OK;

	//获取日志名字
	fp = fopen(file_path,"wb");
	if(fp == NULL){
		ret = errno;
		goto usr_exit;

	}
	//保存光纤段可变信息
	counts = fwrite(pch_fpga_info, sizeof(struct _tagCHInfo),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}

usr_exit:
	if(fp != NULL)
		fclose(fp);

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  read_ch_fpga_info 读取保存在文件里面的信息
 *
 * @param pch_fpga_info
 * @param ch_num
 *
 * @returns 0   
 */
/* ----------------------------------------------------------------------------*/
int32_t read_ch_fpga_info(struct _tagCHInfo *pch_fpga_info,int32_t ch_num)
{
	int32_t ret, counts, tmp, i;
	char file_path[FILE_PATH_LEN] = {0};
	FILE *fp;
	//初始化，全部赋值成0
	memset(pch_fpga_info->para, 0, sizeof(struct _tagFpgaPara)*ch_num);
	pch_fpga_info->num = 0;

	snprintf(file_path,FILE_PATH_LEN , "%s%s.cfg",cfg_path, file_ch_fpga);
	fp = NULL;
	ret = OP_OK;
/*
	//获取日志名字
	fp = fopen(file_path,"rb");
	if(fp == NULL){
		ret = errno;
		goto usr_exit;

	}
	//保存fpga信息
	counts = fread(pch_fpga_info, sizeof(struct _tagCHInfo),1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	fclose(fp);
	fp = NULL;
	//检查是否读的正确
	if(pch_fpga_info->num <= ch_offset || pch_fpga_info->num > (ch_offset + CH_NUM))
		memset(pch_fpga_info, 0, sizeof(struct _tagCHInfo));

	
*/
	pch_fpga_info->num = CH_NUM;
	for(i = 0; i < CH_NUM;i++)
	{
		pch_fpga_info->para[i].slot = card_slot;
		pch_fpga_info->para[i].ch = i;
		pch_fpga_info->para[i].scope_dB = 27;
		//根据奇偶不同取不同的波长
		pch_fpga_info->para[i].lamda = otdrDev[i].ch_ctrl.lamda;

	}

usr_exit:
	if(fp != NULL)
		fclose(fp);

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  save_node_name_address 保存节点名称，和通道使用状态
 *
 * @param pdev_misc 节点名称，地址，设备信息都保存在杂项里面
 *
 * @returns   0 成功，其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t save_node_name_address(const struct _tagDevMisc *pdev_misc)
{

	int32_t ret, counts, size;
	char file_path[FILE_PATH_LEN] = {0};
	FILE *fp;

	snprintf(file_path,FILE_PATH_LEN , "%s%s.cfg",cfg_path, file_node_name);
	fp = NULL;
	ret = OP_OK;

	//获取日志名字
	fp = fopen(file_path,"wb");
	if(fp == NULL){
		ret = errno;
		goto usr_exit;

	}
	//保存光纤段可变信息
	size = sizeof(struct _tagDevNameAddr) + sizeof(struct _tagDevCHState);
	counts = fwrite(pdev_misc,size,1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}

usr_exit:
	if(fp != NULL)
		fclose(fp);

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  reade_node_name_address 读取文件中保存的节点名称和地址
 *	节点名称地址通道使用状态均保存在杂项里面
 * @param pdev_misc
 *
 * @returns   0 成功，其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t read_node_name_address(struct _tagDevMisc *pdev_misc)
{

	int32_t ret, counts, size;
	char file_path[FILE_PATH_LEN] = {0};
	FILE *fp;

	snprintf(file_path,FILE_PATH_LEN , "%s%s.cfg",cfg_path, file_node_name);
	fp = NULL;
	ret = OP_OK;

	//获取日志名字
	fp = fopen(file_path,"rb");
	if(fp == NULL){
		ret = errno;
		goto usr_exit;

	}
	//保存光纤段可变信息
	size = sizeof(struct _tagDevNameAddr) + sizeof(struct _tagDevCHState);
	memset(pdev_misc, 0, size);
	counts = fread(pdev_misc,size,1,fp);
	if(counts != 1){
		ret = errno;
		goto usr_exit;
	}
	pdev_misc->ch_state.state = 0xffffffff;

usr_exit:
	if(fp != NULL)
		fclose(fp);

	get_local_ip("wan0\0",&pdev_misc->name.ip);
	return ret;
}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  check_usr_otdr_test_para 对点名测量的参数进行检查
 *
 * @param pget_otdrdata
 *
 * @returns   0 其他非法值
 */
/* ----------------------------------------------------------------------------*/
int32_t check_usr_otdr_test_para(struct tms_get_otdrdata *pget_otdrdata)
{
	int32_t ret;
	ret = CMD_RET_OK;
	if(pget_otdrdata->pipe < CH_MIN || \
			pget_otdrdata->pipe > CH_MAX || \
			pget_otdrdata->slot < SLOT_MIN || \
			pget_otdrdata->slot > SLOT_MAX){
		ret = CMD_RET_PARA_INVLADE;
		goto usr_exit;
	}
	if(pget_otdrdata->range < 0 || \
			pget_otdrdata->range > MAX_RANG_M){
		ret = CMD_RET_PARA_INVLADE;
		goto usr_exit;
	}


usr_exit:
	return ret;
}

int32_t check_fiber_sec_para(const struct tms_fibersectioncfg *pfiber_sec_cfg)
{
	int32_t ret, i, tmp,ch;
	int32_t start, end;

	struct tms_fibersection_val *fiber_val;
	ret = CMD_RET_OK;
	
	tmp = pfiber_sec_cfg->fiber_hdr->count;
	//如果count等于0，表示要清空光线段
	if(tmp < 0){
		ret = CMD_RET_PARA_INVLADE;
		printf("%s() %d : sec num error %d ch_offset %d\n",\
					__FUNCTION__ ,__LINE__, tmp, ch_offset);
		goto usr_exit;
	}
	ch = pfiber_sec_cfg->otdr_param->pipe;

	//检查通道号,host通道号从1开始
	if(pfiber_sec_cfg->otdr_param->slot != card_slot || \
			pfiber_sec_cfg->otdr_param->pipe < 0 ||\
		       	pfiber_sec_cfg->otdr_param->pipe > CH_NUM)
	{
		ret = CMD_RET_PARA_INVLADE;
		printf("%s() %d : ch error %d ch_offset %d slot %d \n",\
				__FUNCTION__ ,__LINE__, ch, ch_offset, pfiber_sec_cfg->otdr_param->slot);
		goto usr_exit;
	}
	if(tmp == 0){
		printf("%s() %d : clean fiber sec cfg\n",__FUNCTION__ ,__LINE__);
		goto usr_exit;
	}
	//检查量程
	tmp = pfiber_sec_cfg->otdr_param->range;
	if(tmp <= 0 || tmp > MAX_RANG_M){
		ret = CMD_RET_PARA_INVLADE;
		printf("%s() %d : range over flow %d \n",\
					__FUNCTION__ ,__LINE__, tmp);
		goto usr_exit;
	}
	
	tmp = pfiber_sec_cfg->fiber_hdr->count;
	fiber_val = pfiber_sec_cfg->fiber_val;
	for(i = 0; i < tmp;i++)
	{
		start = fiber_val[i].start_coor;
		end = fiber_val[i].end_coor;
		if(fiber_val[i].fibe_atten_init <= 0){
			ret = CMD_RET_PARA_INVLADE;
			goto usr_exit;
		}
		if(start == end ){
			ret = CMD_RET_PARA_INVLADE;
			goto usr_exit;
		}
		if(start > end){
		
			pfiber_sec_cfg->fiber_val[i].start_coor = end;
			pfiber_sec_cfg->fiber_val[i].end_coor = start;
		}
	}


usr_exit:
	return ret;
}
extern int32_t tsk_measur(void * arg);
extern int32_t tsk_debug(void *arg);
extern int32_t tsk_connect(void *arg);
extern int32_t tsk_service(void *arg);
extern pthread_mutex_t mutex_measur;
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  create_usr_tsk 创建tsk_otdr, tsk_schedule任务
 *
 * @returns   如果失败，直接重启
 */
/* ----------------------------------------------------------------------------*/
int32_t create_usr_tsk()
{
	int32_t ret;
	memset(&tsk_measur_info, 0,sizeof(struct _tagThreadInfo));
	memset(&tsk_debug_info, 0,sizeof(struct _tagThreadInfo));
	memset(&tsk_service_info, 0,sizeof(struct _tagThreadInfo));

	pthread_mutex_init(&mutex_measur,NULL);
	if(otdrTestCtrl.mod == OTDR_SERRI)
		ret = pthread_create(&tsk_measur_info.tid,NULL, (void *)tsk_measur, &tsk_measur_info);	
	else
		ret = create_paral_tsk(otdrTestCtrl.ch_num);
	if(ret != 0){
		exit_self(errno, __FUNCTION__, __LINE__, "creat tsk schedule erro\0");
	}
#if 	1 
	if((access("/tmp/debugx",F_OK)) == 0)   
	{   
		printf("测试，不创建连接线程.\n");   
		system("echo debug, no connect tsk >>/app/record");
	}
	else
	{
		ret = pthread_create(&tsk_connect_info.tid,NULL, (void *)tsk_connect, &tsk_connect_info);	
		if(ret != 0){
			exit_self(errno, __FUNCTION__, __LINE__, "creat tsk schedule erro\0");
		}
	}
#endif
#if 	1 
	ret = pthread_create(&tsk_service_info.tid,NULL, (void *)tsk_service, &tsk_service_info);	
	if(ret != 0){
		exit_self(errno, __FUNCTION__, __LINE__, "creat tsk schedule erro\0");
	}
#endif
#if 0
	ret = pthread_create(&tsk_debug_info.tid,NULL, tsk_debug, &tsk_debug_info);	
	if(ret != 0){
		exit_self(errno, __FUNCTION__, __LINE__, "creat tsk schedule erro\0");
	}

#endif
	return 0;
}
int32_t show_tsk_info()
{
	int32_t i;
	printf("tsk_debug id 0x%x top id %d \n",tsk_debug_info.tid, tsk_debug_info.tid);
	printf("tsk_service id 0x%x top id %d \n",tsk_service_info.tid, tsk_service_info.tid);
	if(otdrTestCtrl.mod == OTDR_SERRI)
		printf("tsk_measur id 0x%x top id %d \n",tsk_measur_info.tid, tsk_measur_info.tid);
	else
	{
		for(i = 0; i < otdrTestCtrl.ch_num;i++)
			printf("tsk_measur_p ch(%d) id(0x%x) top id(%d) \n",ptsk_testp_info[i].ch,
					ptsk_testp_info[i].tid, ptsk_testp_info[i].tid);
	}

}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  get_context_by_dst 通过目的地址获取context 
 *
 * @param dst	目的地址，网管服务器，客户端，节点管理器
 * @param pcontext 指向fd最初创建时的context
 *
 * @returns   0成功，其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t get_context_by_dst(int32_t dst, struct tms_context **pcontext)
{
	int ret;
	*pcontext = NULL;
	ret = tms_SelectContextByAddr(dst, pcontext);
	//上述两个函数 1 代表成功， 0失败。转换成0代表成功，其他代表失败
	if(ret == 1 && (*pcontext) != NULL)
		ret = 0;
	else 
		ret = 3;
	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  hb_Ret_Ack 封装了向上发送回应的函数
 *
 * @param ack
 *
 * @returns   0 成功 其他失败
 */
/* ----------------------------------------------------------------------------*/
int32_t hb_Ret_Ack(int32_t dst, struct tms_ack ack)
{
	struct tms_context *dst_context;
	struct glink_addr addr;
	int32_t ret;
	addr.src = ADDR_LOCAL;
	addr.dst = dst;
	addr.pkid = 0;
	dst_context = NULL;

	ret = get_context_by_dst(dst, &dst_context);
	if(!ret){
		addr.pkid = dst_context->pgb->pkid;
		ret =  tms_AckEx(dst_context->fd, &addr, &ack);
	}

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  hb_Ret_Ack_V2 用户向上面反馈操作结果
 *
 * @param addr 地址
 * @param ack	回应吗
 *
 * @returns  非零，代表失败 
 */
/* ----------------------------------------------------------------------------*/
int32_t hb_Ret_Ack_V2(struct glink_addr *addr, struct tms_ack *ack)
{
	struct tms_context *dst_context;
	int32_t ret;
	dst_context = NULL;

	ret = get_context_by_dst(addr->dst, &dst_context);
	if(!ret){
		ret =  tms_AckEx(dst_context->fd, addr, ack);
	}
	
	return ret;

}
//读取槽位号，不成功，就去死,返回槽位号，-1失败
int32_t read_slot()
{

	int32_t ret, slot, read_bytes, i;
	char msg[NUM_CHAR_LOG_MSG] ={0};
	char buf[10] = {0};
	read_bytes = 10;
	slot = 0;
	for(i = 0; i < GPIO_NUM_SLOT;i++)
	{
		ret = read_gpio_val(gpio_fd.slot[i], buf, read_bytes);
		if(ret != read_bytes)
			exit_self(errno, __FUNCTION__, __LINE__, "get slot error\0");

		slot = slot | (buf[5] << i);
	}
	ret = 0;
	//槽位从1开始，但是如果用小板，那么有可能是从0开始
	slot = slot - 1;
	card_slot = slot;
	PR_X("card slot %d \n",card_slot);
	assert(card_slot >= SLOT_MIN && card_slot <= SLOT_MAX);
	ch_offset = 0;
	return slot;

}
//读取网络标志，不成功就去死, 此函数不可重入，线程不安全，只在一个地方调用就可以了
int32_t read_net_flag()
{
	int32_t ret;
	char buf[10] = {0};
	int32_t read_bytes, flag, slot;
	read_bytes = 10;
	quick_lock(&net_flag_lock);
	ret = read_gpio_val(gpio_fd.ip_flag, buf, read_bytes);
	if(ret != read_bytes)
		exit_self(errno, __FUNCTION__, __LINE__, "get net flag error\0");

	flag = buf[5];
	//根据通道偏移量判断槽位
	slot = card_slot;
	//网段标志与之前不同，设置为变化，只有发生了变化，并且与上次读到网段相同方检查本机IP
	if(flag != IPCtrl.flag){
		IPCtrl.flag = flag;
		IPCtrl.chang = 1;
	}
	else if(flag == IPCtrl.flag && IPCtrl.chang)
	{
		IPCtrl.chang = 0;
		IPCtrl.re_connect = 1;
		check_local_ip(flag, slot);
	}

	quick_unlock(&net_flag_lock);
	return flag;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initial_systme_ip 系统初始化IP
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t initial_system_ip()
{
	int32_t ret, flag;
	int32_t read_bytes, slot;
	char buf[10];
	read_bytes = 10;
	ret = 0;
	ret = read_gpio_val(gpio_fd.ip_flag, buf, read_bytes);
	if(ret != read_bytes)
		exit_self(errno, __FUNCTION__, __LINE__, "get read net flag error\0");

	flag = buf[5];

	IPCtrl.flag = flag;
	ret = check_local_ip(flag, card_slot);
	
usr_exit:
	if(ret != OP_OK){
		exit_self(errno, __FUNCTION__, __LINE__, "get net flag error\0");
	}
	return ret;

}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  check_local_ip 根据网段标志和槽位检查本机IP
 *
 * @param flag	网段标志 0 代表1网段 1 代表0网段
 * @param slot	槽位标志 0 192.168.1.201   1 192.168.0.201
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t check_local_ip(int32_t flag, int32_t slot)
{
	char *p;
	char ip[16] = {0}, hoped_ip[16] = {0}, hoped_gw[16];
	int32_t  unuse, ip3, ret, net_sec;
	struct itifo wan0ip;
	ret = 0;
	if (!GetInterfaceInfo("wan0", &wan0ip)) {
		ret = 1;
		printf("%s %d get interface info error \n", __FUNCTION__, __LINE__);
		goto usr_exit;
	}
	p = inet_ntoa((struct in_addr)wan0ip.addr.sin_addr);
	strcpy(ip, p);
	sscanf(ip, "%d.%d.%d.%d", &unuse, &unuse, &ip3, &unuse );
	//期望的本槽位的ip, 通过异或，flag 0 代表1网段，1， 代表0网段
	net_sec = flag ^ 1;
	snprintf(hoped_ip,16 , "192.168.%d.%d",net_sec, slot + 201);	
	snprintf(hoped_gw,16 , "192.168.%d.200",net_sec);	
	
	printf("%s %d cur ip %s hoped ip %s\n", __FUNCTION__, __LINE__,ip, hoped_ip);
	if(strcmp(ip, hoped_ip))
	{
		modifiy_eq_ip(hoped_ip,"255.255.255.0\0", hoped_gw);
		get_local_ip("wan0\0",devMisc.name.ip);
	}
	
		
usr_exit:
	return ret;

}

int32_t get_local_ip(char eth[],char (*ip)[16])
{
	char *p;
	int32_t  ret;
	struct itifo wan0ip;
	ret = 0;
	if (!GetInterfaceInfo(eth, &wan0ip)) {
		ret = 1;
		printf("%s %d get interface info error \n", __FUNCTION__, __LINE__);
		goto usr_exit;
	}
	p = inet_ntoa((struct in_addr)wan0ip.addr.sin_addr);
	strncpy(ip, p,16);
usr_exit:
	PR_X("local ip: %s",ip);
	return ret;

}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  exit_self 自我了断， 发现严重错误，那就死吧
 *
 * @param err_code	错误码
 * @param function[]	哪个函数把程序搞死了
 * @param line		哪一行出现了问题
 * @param msg[]		死之前的遗言
 *
 * @returns		无所谓了吧
 */
/* ----------------------------------------------------------------------------*/
int32_t exit_self(int32_t err_code, const char *function, int32_t line,  char msg[])
{
	char log[128] = {0};
	snprintf(log, 128,"%s %d : errno %d!msg %s",function, line, err_code,msg);
	//LOGW(__FUNCTION__, __LINE__,LOG_LEV_FATAL_ERRO, log);
	//printf("%s \n", log);
	perror(log);
	exit(err_code);
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  get_ret_curv_cmd 根据输入曲线的ID获取返回曲线的ID
 *
 * @param in_cmd	输入曲线id
 * @param ret_cmd	返回曲线id
 *
 * @returns   0 成功，其他没有对应的id
 */
/* ----------------------------------------------------------------------------*/
int32_t get_ret_curv_cmd(int32_t in_cmd, int32_t *ret_cmd)
{
	int32_t ret;
	ret = 0;
	switch(in_cmd)
	{
		case ID_GET_OTDR_DATA:
			*ret_cmd = ID_RET_OTDR_DATA;
			break;

		case ID_GET_CYC_DATA:
			*ret_cmd = ID_RET_CYC_DATA;
			break;

		default:
			PR_X("src cmd 0x%x get ret cmd fail!\n",in_cmd);
			ret = 1;
			*ret_cmd = 0;
			break;
	}

	return ret;
}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  get_inser_loss_diff 获取两个事件点插损差值。如果插损值都存在那么是
 *				  两者差值，如果只有当前值存在，那么就以差值返回
 *				  如果当前事件点没有插损值，则返回失败
 * @param cur_loss		当前事件的插损
 * @param std_loss		标准事件插损
 * @param			返回的插损值
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t get_inser_loss_diff(
		float cur_loss,
		float std_loss,
		float *diff_loss
		)
{
	int32_t ret;
	float loss;
	ret = OP_OK;
	if(cur_loss < RSVD_FLOAT && std_loss < RSVD_FLOAT)
		loss = cur_loss - std_loss;
	else if(cur_loss < RSVD_FLOAT)
		loss = cur_loss;
	else
		ret = 1;

	if(!ret)
		*diff_loss = loss;
	return ret;
}
int32_t get_alarm_lev(
		float loss,
		struct tms_fibersection_val *pfiber_sec
		)
{
	int lev;
	//告警级别为0 代表无告警
	lev = 0;

	if(loss >= pfiber_sec->level1)
		lev = 1;
	else if(loss >= pfiber_sec->level2)
		lev = 2;
	else if(loss >= pfiber_sec->listen_level)
		lev = 3;

	return lev;
}


/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_host_basic_info 获取主机的基本信息
 *
 * @param pcontext
 * @param paddr
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_host_basic_info(
		struct tms_context *pcontext,
		struct glink_addr *paddr)
{
	return 0;
	/*
	int32_t ret, cmd, i, offset, count_every_ch;
	int32_t curv_offset;
	//校验码，节点名称节点地址，硬件版本号，软件版本号
	struct tms_otdr_crc_hdr     otdr_crc_hdr;
	//通道的fpga信息，收到的时候，和读取的时候已经按格式存好
	struct tms_otdr_crc_val      *potdr_crc_val;
	// 通道使用状态
	struct tms_otdr_ch_status   otdr_ch_status;
	//用户配置的测量参数信息
	struct tms_otdr_param_hdr   otdr_param_hdr;
	struct tms_otdr_param_val    otdr_param_val[CH_NUM];
	//光纤段的部分
	struct tms_fibersection_hdr fiber_hdr;
	struct tms_fibersection_val  *pfiber_val;
	struct tms_ack ack;


	struct tms_otdrbaseinfo baseinfo;
	struct glink_addr addr;
	addr.src = ADDR_LOCAL;
	addr.dst = pcontext->pgb->src;
	addr.pkid = pcontext->pgb->pkid;
	
	memset(&ack, 0, sizeof(struct tms_ack));
	ack.cmdid = pcontext->pgb->cmdid;
	ack.errcode = OP_OK;
	ack.slot = card_slot;
	ack.pipe = 0;
	pfiber_val = NULL;
	ret = 0;

	//首先获取光线段配置信息
	strcpy(fiber_hdr.id, "FiberSectionConfig\0");
	memset(&otdr_param_hdr, 0, sizeof(struct tms_otdr_param_hdr));
	strcpy(otdr_param_hdr.id, "OTDRTestParaConfig\0");
	otdr_param_hdr.count = 0;
	//光纤段，测量参数部分
	fiber_hdr.count = 0;
	for(i = 0; i < CH_NUM; i++)
	{
		if(chFiberSec[i].para.is_initialize)
			fiber_hdr.count += chFiberSec[i].para.fiber_hdr.count;
	}
	if(fiber_hdr.count > 0)
	{
		pfiber_val = malloc(sizeof(struct tms_fibersection_val)*fiber_hdr.count);
		if(pfiber_val == NULL && fiber_hdr.count > 0)
		{
			ack.errcode = errno;
			hb_Ret_Ack(pcontext->pgb->src, ack);
			printf("%s %d new buf fail. \n", __FUNCTION__, __LINE__);
			exit_self(errno,__FUNCTION__, __LINE__,"new buf fail\0");
		}

		offset = 0;
		curv_offset = 0;
		for(i = 0; i < CH_NUM;i++)
		{
			if(chFiberSec[i].para.is_initialize)
			{
				count_every_ch = chFiberSec[i].para.fiber_hdr.count;
				memcpy(&pfiber_val[offset], chFiberSec[i].para.fiber_val,\
						count_every_ch*sizeof(struct tms_fibersection_val));
				offset += count_every_ch;
				memcpy(&otdr_param_val[curv_offset].range, &chFiberSec[i].para.otdr_param.range,
						sizeof(struct tms_otdr_param_val) - 4);
				otdr_param_val[curv_offset].pipe = chFiberSec[i].para.fiber_val[0].pipe_num; 
				curv_offset++;
				otdr_param_hdr.count++;
			}
		}
	}
	//通道使用状态
	strcpy(otdr_ch_status.id, "PipeState\0");
	otdr_ch_status.ch_status = devMisc.ch_state.state;
	if(ch_offset == 1)
		otdr_ch_status.ch_status = devMisc.ch_state.state & 0x000000ff;
	else                             
		otdr_ch_status.ch_status = (devMisc.ch_state.state << 8) & 0x0000ff00;


	strcpy(otdr_crc_hdr.id, "OTDRInfo\0");
	strcpy(otdr_crc_hdr.name, devMisc.name.name);
	strcpy(otdr_crc_hdr.addr, devMisc.name.ip);
	strcpy(otdr_crc_hdr.hw_ver, &DevVersion.hw[0]);
	otdr_crc_hdr.count = chFpgaInfo.num;
	potdr_crc_val = (struct tms_otdr_crc_val *) chFpgaInfo.para;

	baseinfo.fiber_hdr = &fiber_hdr;
	baseinfo.fiber_val = pfiber_val;
	baseinfo.otdr_ch_status = &otdr_ch_status;
	baseinfo.otdr_crc_hdr = &otdr_crc_hdr;
	baseinfo.otdr_crc_val = potdr_crc_val;
	baseinfo.otdr_param_hdr = &otdr_param_hdr;
	baseinfo.otdr_param_val = otdr_param_val;



	tms_OTDRBasicInfo(pcontext,&addr,&baseinfo);
	if(pfiber_val != NULL)
		free(pfiber_val);

	return ret;	
*/
}


/* --------------------------------------------------------------------------*/
/**
 * @synopsis  get_ch_total_alarm 获取某通道的全部告警
 *
 * @param arm_val[]	告警缓冲区
 * @param		通道配置参数
 *
 * @returns		返回告警数目 
 */
/* ----------------------------------------------------------------------------*/
int32_t get_ch_total_alarm(
		struct tms_alarmlist_val alarm_val[], 
		struct _tagUpOtdrCurv *pcurv,
		struct _tagCHFiberSec *pfiber_sec,
		struct _tagOtdrDev *potdr_dev
		)
{
	int32_t ret, i, alarm_num;
	struct _tagFiberSecCfg *psec_para;
	struct _tagSecFiberAlarm *palarm;
	
	alarm_num = 0;
	quick_lock(& pfiber_sec->lock);
	psec_para = &pfiber_sec->para;
	palarm = &pfiber_sec->alarm;
	if(!potdr_dev->ch_ctrl.enable || !psec_para->is_initialize || !palarm->alarm_num )
		goto usr_exit;


	for(i = 0; i < palarm->sec_num && i < SEC_NUM_IN_CH ;i++)
	{
		if(palarm->buf[i].lev > FIBER_ALARM_LEV0){
			memcpy(&alarm_val[alarm_num], &palarm->buf[i], sizeof(struct tms_alarmlist_val));
			alarm_num ++;
		}
	}
	if(alarm_num > 0)
			memcpy(pcurv, palarm->pcurv, sizeof(struct _tagUpOtdrCurv));
usr_exit:
	quick_unlock(&pfiber_sec->lock);
	return alarm_num;

	
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  convert_ch_cyc_curv2host 将周期性测量曲线转换成host格式
 *		如果并行otdr模式，会出现同步的问题，必须将曲线数据拷贝到缓冲区
 *		否则，获取每个通道的cyc资源锁只能哈哈了
 * @param ch		通道
 * @param line_val[]	host格式
 * @param		本地格式
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t convert_ch_cyc_curv2host(
		int32_t ch,
		struct tms_alarmline_val line_val[], 
		struct _tagUpOtdrCurv *pcyc_curv
		)
{
	int32_t ret, total_size;
	line_val->pipe = ch + ch_offset;
	//告警返回曲线长度测量参数，测量结果，数据点，事件点头，事件部分（只有这一部分可变）+ sizeof(int32_t)
	//测量参数结构体中多出一个int类型的变量
	line_val->datalen =  sizeof(struct tms_ret_otdrparam) - sizeof(int32_t)  + sizeof(struct tms_test_result) +\
				sizeof(struct tms_hebei2_data_hdr) + sizeof(struct tms_hebei2_event_hdr) + \
				sizeof(int16_t)*pcyc_curv->data.num + \
				sizeof(struct tms_hebei2_event_val)*pcyc_curv->event.num + sizeof(int32_t);
	//将参数值拷贝过去
	//memcpy(&line_val->ret_otdrparam.range,   &pcyc_curv->para ,sizeof(struct _tagUpOtdrPara ));
	//这个地方可能会出错，如果发送告警的时候使用line->ret_otdrparam成员变量pipe会出错
	line_val->ret_otdrparam = (struct tms_ret_otdrparam *)&pcyc_curv->para;
	line_val->hebei2_data_hdr = (struct tms_hebei2_data_hdr*)  &pcyc_curv->data.id[0];
	line_val->hebei2_data_val = (struct tms_hebei2_data_val*) &pcyc_curv->data.buf[0];
	line_val->hebei2_event_hdr = (struct tms_hebei2_event_hdr *) &pcyc_curv->event.id[0];
	line_val->hebei2_event_val = (struct tms_hebei2_event_val*) &pcyc_curv->event.buf[0];
	line_val->test_result = (struct tms_test_result *)&pcyc_curv->result;
	return 0;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_total_curalarm2host 向host返回全部的告警
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_total_curalarm2host()
{
	struct glink_addr addr;
	struct tms_context *context;
	int ret;
	if(!otdrTestCtrl.is_send_alarm){
		PR_X("first cyc monitor is not over please wait,monitor num ret %d \n",otdrTestCtrl.monitor_num);
		return 0;
	}

	addr.src = ADDR_LOCAL;
	/*
	 * 发送次序，CU, 网关服务器，节点管理器，有一个发送成功，则直接结束
	 */
	addr.dst = ADDR_CU;
	ret = get_context_by_dst(addr.dst, &context);
	if(ret == 0)
		goto usr_exit;

	addr.dst = ADDR_HOST_SERVER;
	ret = get_context_by_dst(addr.dst, &context);
	if(ret == 0)
		goto usr_exit;

	addr.dst = ADDR_HOST_NODE;
	ret = get_context_by_dst(addr.dst, &context);
	if(ret == 0)
		goto usr_exit;
	PR_X("not find fd  to send total alarm");
	return 0;
usr_exit:
	ret_total_curalarm2host_V2(&addr);
	return 0;
}
//只在本文件中使用
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_total_curalarm2host_V2 根据地址选择发送目标
 *
 * @param dst 发送者地址
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_total_curalarm2host_V2(struct glink_addr *paddr)
{
	int32_t ret, i, j,alarm_total, alarm_ch, line_num, curv_buf_len;
	int32_t alloc_size;
	struct tms_curalarm fiber_alarm;
	struct tms_alarmlist_hdr	alarmlist_hdr;
	struct tms_alarmline_hdr	alarmline_hdr;
	struct tms_alarmline_val	*alarmline_val;
	struct _tagUpOtdrCurv *curv_buf;
	struct tms_context *context;
	struct tms_alarmlist_val    *alarmlist_val;
	int32_t dst;
	dst = paddr->dst;

	if(!otdrTestCtrl.is_send_alarm){
		PR_X("first cyc monitor is not over please wait,monitor num ret %d \n",otdrTestCtrl.monitor_num);
		return 0;
	}	

	ret = get_context_by_dst(dst, &context);
	if(ret != 0){
		printf("%s %d get dst %x fd error ret %d\n",__FUNCTION__,__LINE__,dst,ret);
		return 0;
	}

	//fuck, 一种业务类型有两个不同的值,fuck 1万次
	alarmlist_hdr.card_type = 3;
	alarmlist_hdr.slot = card_slot;
	curv_buf = NULL;
	alloc_size = 0;
	alarmlist_val = malloc( sizeof(struct tms_alarmlist_val)*(SEC_NUM_IN_CH*CH_NUM));
	if(alarmlist_val == NULL)
		exit_self(errno, __FUNCTION__,__LINE__,"malloc alarmlist_val error\0");
	alarmline_val = malloc( sizeof(struct tms_alarmline_val)*CH_NUM);
	if(alarmline_val == NULL)
		exit_self(errno, __FUNCTION__,__LINE__,"malloc alarmline_val error\0");

	//存放具体告警缓冲区
	memset(alarmlist_val, 0, sizeof(struct tms_alarmlist_val)*(SEC_NUM_IN_CH*CH_NUM));
	//包含了曲线的指针已经头
	memset(alarmline_val, 0, sizeof(struct tms_alarmline_val)*CH_NUM);
	curv_buf_len = 0;
	for(i = 0; i < CH_NUM;i ++)	
	{
		if(otdrDev[i].ch_ctrl.enable && chFiberSec[i].para.is_initialize && chFiberSec[i].alarm.alarm_num)
			curv_buf_len++;
	}
	//没有发现告警？
	if( !curv_buf_len )
	{
		alarmlist_hdr.count = 0;
		alarmline_hdr.count = 0;
		goto usr_exit;
	}
	alloc_size = sizeof(struct _tagUpOtdrCurv)*curv_buf_len;
	curv_buf = malloc(alloc_size);
	if(!curv_buf){
		ret = errno;
		exit_self(errno,__FUNCTION__, __LINE__,"new buf fail\0");
		goto usr_exit;
	}
	alarm_total = 0;
	line_num = 0;
	for(i = 0; i < CH_NUM;i++)
	{
		//如果分配完曲线后，有可能新的通道产生告警那就对不起，不处理了
		if(line_num >= curv_buf_len)
			break;
		alarm_ch = get_ch_total_alarm(&alarmlist_val[alarm_total],&curv_buf[line_num],&chFiberSec[i],&otdrDev[i]);
		if(alarm_ch){
			//如果是并行otdr下面的方法很有必要
			convert_ch_cyc_curv2host(i,&alarmline_val[line_num],&curv_buf[line_num]);
			line_num++;
		}
		alarm_total += alarm_ch;
	}
	alarmlist_hdr.count = alarm_total;
	alarmline_hdr.count = line_num;
	ret = OP_OK;
usr_exit:
	fiber_alarm.alarmline_hdr = &alarmline_hdr;
	fiber_alarm.alarmline_val = alarmline_val;
	fiber_alarm.alarmlist_hdr = &alarmlist_hdr;
	fiber_alarm.alarmlist_val = alarmlist_val;
	//2016-11-07 将告警发送给网管，节点管理器
	tms_CurAlarm_V2(context->fd,paddr,&fiber_alarm);
	//曲线发给201，由201综合打包发送到cu
	//tms_CurAlarm_V2(g_201fd,NULL,&fiber_alarm);
	if(curv_buf)
	{
		free(curv_buf);
		curv_buf = NULL;
	}
	if(alarmlist_val)
	{
		free(alarmlist_val);
		alarmlist_val = NULL;
	}
	if(alarmline_val)
	{
		free(alarmline_val);
		alarmline_val = NULL;
	}
	return ret;
}

int32_t save_data_pt(const char file[], float *An, int32_t len)
{
	FILE *fp;
	int i;
	fp = fopen(file, "w");
	if(!fp)
		goto usr_exit;
	for(i = 0; i < len; i++)
		fprintf(fp, "%f\r\n", An[i]);
	fclose(fp);
usr_exit:
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  modifiy_eq_ip  设置IP，通过调用Menglong接口实现
 *
 * @param ip[]
 * @param mask[]
 * @param gw[]
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t modifiy_eq_ip(const char ip[], const char mask[], const char gw[])
{
	int32_t ret;
	char set_ip[128] = {0};
	snprintf(set_ip, 128, "/app/freebox ip wan0 %s %s %s", ip, mask, gw);
	system(set_ip);
	system("sync");
	printf("%s %d %s \n", __FUNCTION__, __LINE__, set_ip);
	printf("%s %s %s \n", ip, mask, gw);
	ret = OP_OK;
	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_host_cyc_curv 返回周期性测量曲线,存在一个问题，假如该通道的
 *				周期性测量曲线不存在怎么办？缺少必要的返回码
 * @param pcontext
 * @param pcyc_curv
 * @param ch		从0开始的偏移量
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_host_cyc_curv(
		const struct tms_context *pcontext, 
		struct _tagCycCurv *pcyc_curv,
		int32_t ch)
{
	int32_t ret, cmd;
	int32_t  offset, event_count;
	struct tms_ack ack;
	ret = OP_OK;
	struct tms_ret_otdrdata		hebei2_otdrdata;
	struct tms_ret_otdrparam	ret_otdrparam;
	struct tms_test_result		*test_result;
	struct tms_hebei2_data_hdr	*hebei2_data_hdr;
	struct tms_hebei2_data_val	*hebei2_data_val;
	struct tms_hebei2_event_hdr	*hebei2_event_hdr;
	struct tms_hebei2_event_val	*hebei2_event_val;
	struct glink_addr addr;

	addr.dst = pcontext->pgb->src;
	addr.src = ADDR_LOCAL;
	addr.pkid = pcontext->pgb->pkid;
	
	test_result = (struct tms_test_result *)&pcyc_curv->curv.result;
	hebei2_data_hdr = (struct tms_hebei2_data_hdr *)pcyc_curv->curv.data.id;
	hebei2_data_val = (struct tms_hebei2_data_val *)pcyc_curv->curv.data.buf;
	hebei2_event_hdr = (struct tms_hebei2_event_hdr *)(pcyc_curv->curv.event.id);
	hebei2_event_val = (struct tms_hebei2_event_val *)pcyc_curv->curv.event.buf;
	//检查是有周期性测量曲线
	if(hebei2_data_hdr->count <= 0)
	{
		ret = CMD_RET_OTHRER_ERROR;
		printf("%s %d ch %d cyc curve not exist \n", __FUNCTION__, __LINE__, ch + ch_offset);
		goto usr_exit;
	}


	ret = get_ret_curv_cmd(pcontext->pgb->cmdid, &cmd);
	if(ret)
	{
		ret = CMD_RET_OTHRER_ERROR;
		printf("%s %d ch %d get ret cmd error cmd 0x%x \n",\
				__FUNCTION__, __LINE__, ch + ch_offset, pcontext->pgb->cmdid);
		goto usr_exit;
	}
	hebei2_otdrdata.hebei2_data_hdr = hebei2_data_hdr;
	hebei2_otdrdata.hebei2_data_val = hebei2_data_val;
	hebei2_otdrdata.hebei2_event_hdr = hebei2_event_hdr;
	hebei2_otdrdata.hebei2_event_val = hebei2_event_val;
	hebei2_otdrdata.ret_otdrparam = &ret_otdrparam;
	hebei2_otdrdata.test_result = test_result;

	quick_lock(&pcyc_curv->lock);
	memcpy(&ret_otdrparam, &pcyc_curv->curv.para, sizeof(struct _tagUpOtdrPara));
	tms_RetOTDRData(pcontext->fd, &addr, &hebei2_otdrdata, cmd);		

	quick_unlock(&pcyc_curv->lock);
usr_exit:
	if(ret){
		memset(&ack, 0, sizeof(struct tms_ack));
		ack.slot = card_slot;
		ack.pipe = ch;
		ack.errcode = ret;
		hb_Ret_Ack(pcontext->pgb->src, ack);
	}

	return ret;
}
		
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_host_std_curv 返回标准曲线
 *
 * @param pcontext
 * @param pchfiber_sec
 * @param ch
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_host_std_cfg(
		const struct tms_context *pcontext, 
		struct _tagCHFiberSec *pchfiber_sec,
		int32_t ch)
{
	int32_t ret, cmd, is_lock;
	int32_t  offset, event_count;
	struct tms_ack ack;
	struct tms_fibersectioncfg fiber_cfg;
	struct _tagFiberSecCfg *pfiber_cfg;
	struct glink_addr addr;

	addr.dst = pcontext->pgb->src;
	addr.src = ADDR_LOCAL;
	addr.pkid = pcontext->pgb->pkid;
	

	pfiber_cfg = &pchfiber_sec->para;

	
	ret = 0;
	quick_lock(&pchfiber_sec->lock);
	is_lock = 1;
	if(!pfiber_cfg->is_initialize){
		ret = CMD_RET_CH_UNCFG;
		goto usr_exit;
	}

	fiber_cfg.event_hdr = &pfiber_cfg->event_hdr;
	fiber_cfg.event_val = pfiber_cfg->event_val;
	fiber_cfg.fiber_hdr= &pfiber_cfg->fiber_hdr;
	fiber_cfg.fiber_val = pfiber_cfg->fiber_val;
	fiber_cfg.otdr_hdr = &pfiber_cfg->otdr_hdr;
	fiber_cfg.otdr_val = pfiber_cfg->otdr_val;
	fiber_cfg.otdr_param = &pfiber_cfg->otdr_param;
	fiber_cfg.test_result = &pfiber_cfg->test_result;

	tms_RetFiberCfg(pcontext, &addr, &fiber_cfg);
	ret = 0;


usr_exit:

	if(is_lock)
		quick_unlock(&pchfiber_sec->lock);
	if(ret){
		memset(&ack, 0, sizeof(struct tms_ack));
		ack.slot = card_slot;
		ack.pipe = ch;
		ack.errcode = ret;
		ack.cmdid = cmd;
		hb_Ret_Ack(pcontext->pgb->src, ack);
	}

	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_host_statis_data 返回统计数据
 *
 * @param ch
 * @param pcontext
 * @param pchfiber_sec
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_host_statis_data(
		int32_t ch, 
		struct tms_context *pcontext,
		struct _tagCHFiberSec *pchfiber_sec)
{
	int32_t ret, is_lock;
	struct _tagFiberStatisData statis;
	struct tms_getstatus_data_hdr statis_hdr;
	struct tms_getstatus_data_val *val;
	struct tms_ack ack;
	struct glink_addr addr;

	addr.dst = pcontext->pgb->src;
	addr.src = ADDR_LOCAL;
	addr.pkid = pcontext->pgb->pkid;
	is_lock = 0;
	ret = OP_OK;
	memset(&ack, 0, sizeof(struct tms_ack));
	ack.cmdid = pcontext->pgb->cmdid;
	ack.slot = card_slot;
	ack.pipe = ch;

	quick_lock(& pchfiber_sec->lock);
	is_lock = 1;
	if(!pchfiber_sec->para.is_initialize)
	{
		ret = CMD_RET_CH_UNCFG;
	       goto usr_exit;
	}
	statis_hdr.count = pchfiber_sec->statis.sec_num;
	statis_hdr.pipe = pchfiber_sec->statis.ch;
	statis_hdr.slot = card_slot;
	val = (	struct tms_getstatus_data_val *)pchfiber_sec->statis.buf;
	tms_RetStatusData(pcontext,&addr, &statis_hdr,val,statis_hdr.count);

usr_exit:
	if(is_lock)
		quick_unlock(& pchfiber_sec->lock);
	ack.errcode = ret;
	if(ret)
		hb_Ret_Ack(pcontext->pgb->src, ack);
	return ret;
}
int16_t get_pkid()
{
	quick_lock(&ctrlPkid.lock);
	ctrlPkid.pkid++;
	quick_unlock(&ctrlPkid.lock);
	return ctrlPkid.pkid;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  ret_host_otdr_curv 返回点名测量曲线
 *
 * @param tr		算法模块测量结果
 * @param pusrTest	用户点名测量信息
 *
 * @returns  		0 成功，其他失败 
 */
/* ----------------------------------------------------------------------------*/
int32_t ret_host_otdr_curv(
		const OtdrTestResult_t *tr, 
		const struct _tagUsrOtdrTest *pusrTest)
{
	struct glink_addr dst_addr;
	int32_t ret_cmd;
	int32_t ret,event_count;
	struct tms_ack ack;
	struct tms_context *pcontext;
	struct tms_ret_otdrdata hebei2_otdrdata;
	struct tms_ret_otdrparam    ret_otdrparam;
	struct tms_test_result      test_result;
	struct tms_hebei2_data_hdr  hebei2_data_hdr;
	struct tms_hebei2_data_val *hebei2_data_val;
	struct tms_hebei2_event_hdr hebei2_event_hdr;
	struct tms_hebei2_event_val hebei2_event_val[10];
	struct tms_hebei2_event_val *pevent_buf;
	int8_t cur_time[TIME_STR_LEN] = {0};
	const char* pFormatTime = "%Y-%m-%d %H:%M:%S";
	struct _tagHostOtdrPara *pHostPara;
	struct _tagHostTestResult *pHostTr;
	uint16_t *data_buf;
	
	dst_addr.dst = pusrTest->src_addr.src;
	dst_addr.src = ADDR_LOCAL;
	dst_addr.pkid = pusrTest->src_addr.pkid;
	get_sys_time(cur_time, 0, pFormatTime);
	ret = get_ret_curv_cmd(pusrTest->cmd,&ret_cmd);

	if(ret != 0){
		ret = CMD_RET_TEST_ERROR;
		memset(&ack, 0, sizeof(ack));
		ack.slot = card_slot;
		ack.pipe = tr->tp.ChanNum;
		ack.cmdid = pusrTest->cmd;
		ack.errcode = ret;
		goto fail;
	}
	pcontext = NULL;
	ret = get_context_by_dst(dst_addr.dst,&pcontext);

	if(ret != 0 || pcontext == NULL){
		ret = CMD_RET_TEST_ERROR;
		goto fail;
	}

	pevent_buf = NULL;
	pHostPara = (struct _tagHostOtdrPara *)(&ret_otdrparam);
	convert_para_algor2host(&tr->tp, pHostPara);
	pHostPara->slot = pusrTest->para.slot;

	pHostTr = (struct _tagHostTestResult *)&test_result.range;
	convert_tr_algor2host(tr, pHostTr);


	hebei2_data_hdr.count = DATA_LEN - 1000;
	data_buf = malloc(sizeof(uint16_t)*DATA_LEN);
	if(data_buf == NULL){
		PR_X("malloc data buf error data_num %d \n",DATA_LEN);
			exit_self(errno, __FUNCTION__, __LINE__, "alloc data buf error\0");
	}
	hebei2_data_val = (struct tms_hebei2_data_val *)data_buf;
	convert_data_algor2host(tr, data_buf, hebei2_data_hdr.count);

	event_count = tr->EventNum;

	if(event_count > 10){
		pevent_buf = malloc(sizeof( struct tms_hebei2_event_val)*event_count);
		if(!pevent_buf){
			printf("%s %s() %d, alloc error, event_num %d \n", __FILENAME__, __FUNCTION__,\
					__LINE__, event_count);
			exit_self(errno, __FUNCTION__, __LINE__, "alloc event buf error\0");
		}
	}
	else
		pevent_buf = hebei2_event_val;

	convert_event_algor2host(tr, pevent_buf, MAX_EVENT_NUM);

	strcpy(hebei2_data_hdr.dpid,"OTDRData\0");
	strcpy(test_result.result, "OTDRTestResultInfo\0");
	strcpy(hebei2_event_hdr.eventid, "KeyEvents\0");
	hebei2_otdrdata.hebei2_data_hdr = &hebei2_data_hdr;
	hebei2_otdrdata.hebei2_data_val = hebei2_data_val;
	hebei2_otdrdata.hebei2_event_hdr = &hebei2_event_hdr;
	hebei2_otdrdata.hebei2_event_val = pevent_buf;
	hebei2_otdrdata.ret_otdrparam = &ret_otdrparam;
	hebei2_otdrdata.test_result = &test_result;
	hebei2_event_hdr.count = event_count;
	tms_RetOTDRData(pcontext->fd, &dst_addr, &hebei2_otdrdata, ret_cmd);
	if(event_count > 10){
		free(pevent_buf);
		pevent_buf = NULL;
	}
	if(data_buf != NULL){
		free(data_buf);
		data_buf = NULL;
	}
	return ret;
fail:
	hb_Ret_Ack(dst_addr.dst,ack);
	return ret;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  refresh_ch_state 更新通道使能状态
 *
 * @param state	通道是否使能
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t refresh_ch_state(int32_t state)
{
	int32_t i;
	int8_t state_ch;
	state_ch = state & 0xff;

	for(i = 0; i < CH_NUM; i++)
		otdrDev[i].ch_ctrl.enable = (state_ch >> i)& 0x1;

	return 0;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  adjust_fiber_sec_cfg_ch 光线段配置文件中的通道号需要根据当前
 * 					ch_offset来重新修正
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t adjust_fiber_sec_cfg_ch()
{
	int32_t i; 

	for(i = 0; i < CH_NUM;i++)
	{
		quick_lock(&chFiberSec[i].lock);
		if(chFiberSec[i].para.is_initialize)
		{
			chFiberSec[i].para.otdr_param.slot = card_slot;
			convert_stdcfg_host2alarmodule(&chFiberSec[i].para,&chFiberSec[i].adpt_moudle);	
		}
		quick_unlock(&chFiberSec[i].lock);
	}
	return 0;
}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  set_ch_alarm_status 设置通道告警状态，如果通道有告警，点灯
 *
 * @param ch
 * @param val
 * @param pch_dis
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t set_ch_alarm_status(int32_t ch, int32_t val, struct _tagCHAlarmDis *pch_dis)
{	
	int32_t index, tmp;
	assert(val == 0 || val == 1);
	assert(ch >= 0 || ch < CH_NUM);
	/*
	 * 2017-09-01 8通道是每两个通道共享一个告警灯
	 * 因此需要特别处理，不排除将来的情况发生变化
	 * 此处的修改兼容了河北8通道TMS400 2CH 4CH
	*/
	if(CH_NUM < 8)
		write_gpio_val(gpio_fd.alarm_ch[ch],val);
	else if(CH_NUM == 8)
	{
		index = ch / 2;
		if(ch % 2 == 0)
			tmp = ch + 1;
		else
			tmp = ch - 1;

		//只有两个通道全部为0，告警才消失
		if((val == 0 && pch_dis->ch[tmp] == 0) || (val == 1))
		                write_gpio_val(gpio_fd.alarm_ch[index],val);

	}
	
	if(val != pch_dis->ch[ch])
	{
		if(val)
			pch_dis->alarm_num++;
		else
			pch_dis->alarm_num--;
		pch_dis->ch[ch] = val;
	}
	assert(pch_dis->alarm_num >= 0);
	assert(pch_dis->alarm_num <= CH_NUM );
	/*
	 * alarm_total 要输出给cu，低有效
	 * alarm_total_v1 是点灯，高有效
	*/
	if(pch_dis->alarm_num > 0)
		write_gpio_val(gpio_fd.alarm_total,0 );
	else  
		write_gpio_val(gpio_fd.alarm_total,1);

usr_exit:
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  reset_all_alarm_led 系统初始化的时候需要将所有的灯
 *
 * @param pgpio_fd
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t reset_all_alarm_led(struct _tagGpioFd *pgpio_fd)
{
	int32_t i;
	for(i = 0; i < GPIO_NUM_CH_ALARM; i++)
		write_gpio_val(pgpio_fd->alarm_ch[i],0);

	write_gpio_val(pgpio_fd->alarm_total_1, 0 );
	write_gpio_val(pgpio_fd->alarm_total, 1 );

	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  run_led_blink 运行灯闪烁
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t run_led_blink()
{
	static int32_t val = 0;
	//灯闪烁
	if(val){
		val = 0;
		write_gpio_val(gpio_fd.run, val);
	}
	else {
		val = 1;
		write_gpio_val(gpio_fd.run, val);
	}

	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  light_all_led 点亮所有的灯
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
int32_t light_all_led(int32_t val)
{
	int32_t i;
	if(!gpio_fd.is_ok){
		PR_X("gpio not opened.");
		return 0;
	}
	assert(val == 0 ||val == 1);
	for(i = 0; i < GPIO_NUM_CH_ALARM;i++)
	{
		write_gpio_val(gpio_fd.alarm_ch[i], val);
	}
	write_gpio_val(gpio_fd.run, val);
	write_gpio_val(gpio_fd.alarm_total_1, val);
	return 0;
}
int32_t RetLocalCardType(struct tms_context *pcontext)
{
	int32_t ret;
	struct glink_addr addr;
	struct tms_ret_card_type card_type;

	memset(&card_type, 0, sizeof(struct tms_ret_card_type));
	card_type.slot = card_slot;
	card_type.type = LOCAL_CARD_TYPE;
	addr.dst = ADDR_CU;
	addr.src = ADDR_LOCAL;
	addr.pkid = get_pkid();


	ret = tms_RetCardType_V1(pcontext, &addr, &card_type);
	return 0;
}
/*
 **************************************************************************************
 *  函数名称：按照当前格式获取系统时间
 *  函数描述：get_sys_time
 *                ：
 *  入口参数：存放字符串的buf, 时间格式
 *  返回参数：如果成功，返回0，其他值不成功
 *  作者       ：wen
 *  日期       ：2016-04-15
 *  修改日期：
 *  修改内容：
 *                ：
 **************************************************************************************
 */
int get_sys_time(char time_buf[], int offset, const char format[])
{
	int ret;
	time_t now, usr_now;
	struct tm tm_now, *ptm;
	ret = LOG_RET_SUCCESS;
	now = time(NULL);
	usr_now = now - offset;
	ptm = (struct tm *)localtime_r((const time_t * )(&usr_now),&tm_now);
	if(ptm == NULL){
		ret = -1;
		goto usr_exit;
	}
	strftime(time_buf, 20, format, &tm_now);
	//printf("%s(): Line : %d  %x %x \n",  __FUNCTION__, __LINE__, ptm, &tm_now);
usr_exit:
	return ret;
}
int32_t print_fiber_sec_loss(int32_t ch)
{
	int32_t i;
	struct _tagSecLoss *psec_loss;
	
	psec_loss = &otdrDev[ch].ch_ctrl.sec_loss;
	if(ch < 0 || ch >= CH_NUM)
	{
		printf("%d 输入非法.最小通道数目0，最大通道数目%d！\n",ch,CH_NUM);
		goto usr_exit;
	}
	printf("----------------------------------\n");
	printf("ch %d sec_num %d line_b*0.67 %f \n", ch, psec_loss->sec_num,psec_loss->alarm_dis);
	for(i = 0; i < psec_loss->sec_num;i++)
	{
		printf("dis: %f	loss: %f\n",psec_loss->val[i].len, psec_loss->val[i].loss);
	}
	printf("----------------------------------\n");
usr_exit:
	return 0;
}
//按照C风格编译
#ifdef __cplusplus
}
#endif
